import { Injectable, NotFoundException, BadRequestException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { v4 as uuidv4 } from 'uuid';
import { Website } from './entities/website.entity';
import { PageView } from './entities/page-view.entity';
import { TrackingLoggerService } from './tracking-logger.service';

interface CacheEntry {
  data: any;
  timestamp: number;
  ttl: number;
}

@Injectable()
export class WebsiteService {
  private readonly cache = new Map<string, CacheEntry>();
  private readonly cacheTTL = 5 * 60 * 1000; // 5分钟缓存

  constructor(
    @InjectRepository(Website)
    private websiteRepository: Repository<Website>,
    @InjectRepository(PageView)
    private pageViewRepository: Repository<PageView>,
    private trackingLogger: TrackingLoggerService,
  ) {}

  private getCacheKey(key: string): string {
    return `tracking:${key}`;
  }

  private getFromCache(key: string): any {
    const cacheKey = this.getCacheKey(key);
    const entry = this.cache.get(cacheKey);
    if (entry && (Date.now() - entry.timestamp) < entry.ttl) {
      return entry.data;
    }
    if (entry) {
      this.cache.delete(cacheKey);
    }
    return null;
  }

  private setCache(key: string, data: any, ttl: number = this.cacheTTL): void {
    const cacheKey = this.getCacheKey(key);
    this.cache.set(cacheKey, {
      data,
      timestamp: Date.now(),
      ttl
    });
  }

  async createWebsite(createWebsiteDto: any): Promise<Website> {
    const existingWebsite = await this.websiteRepository.findOne({
      where: { domain: createWebsiteDto.domain },
    });
    if (existingWebsite) {
      throw new BadRequestException('网站已存在');
    }
    const website = this.websiteRepository.create({
      ...createWebsiteDto,
      trackingId: `track_${uuidv4().replace(/-/g, '')}`,
      isActive: true,
    });
    const result = await this.websiteRepository.save(website);
    const savedWebsite = Array.isArray(result) ? result[0] : result;
    this.setCache(`website:${savedWebsite.id}`, savedWebsite);
    this.setCache(`website:trackingId:${savedWebsite.trackingId}`, savedWebsite);
    return savedWebsite;
  }

  async updateWebsite(id: number, updateWebsiteDto: any): Promise<Website> {
    const website = await this.getWebsiteById(id);
    Object.assign(website, updateWebsiteDto);
    const updatedWebsite = await this.websiteRepository.save(website);
    this.setCache(`website:${id}`, updatedWebsite);
    this.setCache(`website:trackingId:${updatedWebsite.trackingId}`, updatedWebsite);
    return updatedWebsite;
  }

  async deleteWebsite(id: number): Promise<void> {
    const website = await this.getWebsiteById(id);
    await this.pageViewRepository.delete({ websiteId: id });
    await this.websiteRepository.delete(id);
    this.cache.delete(this.getCacheKey(`website:${id}`));
    this.cache.delete(this.getCacheKey(`website:trackingId:${website.trackingId}`));
    this.cache.delete(this.getCacheKey('websites:all'));
  }

  async deleteAllWebsites(): Promise<void> {
    await this.pageViewRepository.clear();
    await this.websiteRepository.clear();
    this.cache.clear();
  }

  async getAllWebsites(): Promise<Website[]> {
    const cacheKey = 'websites:all';
    const cached = this.getFromCache(cacheKey);
    if (cached) {
      return cached;
    }
    const websites = await this.websiteRepository.find({
      order: { createdAt: 'DESC' },
    });
    this.setCache(cacheKey, websites, 2 * 60 * 1000); // 2分钟缓存
    return websites;
  }

  async getWebsiteById(id: number): Promise<Website> {
    const cacheKey = `website:${id}`;
    const cached = this.getFromCache(cacheKey);
    if (cached) {
      return cached;
    }
    const website = await this.websiteRepository.findOne({
      where: { id },
      relations: ['pageViews']
    });
    if (!website) {
      throw new NotFoundException('网站不存在');
    }
    this.setCache(cacheKey, website);
    return website;
  }

  async getWebsiteByTrackingId(trackingId: string): Promise<Website> {
    const cacheKey = `website:trackingId:${trackingId}`;
    const cached = this.getFromCache(cacheKey);
    if (cached) {
      return cached;
    }
    const website = await this.websiteRepository.findOne({
      where: { trackingId, isActive: true },
    });
    if (website) {
      this.setCache(cacheKey, website);
    }
    return website;
  }

  async getEmbedCode(id: number): Promise<{ scriptTag: string, trackingId: string, scriptUrl: string }> {
    const website = await this.getWebsiteById(id);
    const apiBaseUrl = process.env.API_BASE_URL || 'http://localhost:3001';
    const scriptUrl = `${apiBaseUrl}/tracking/script.js`;
    const scriptTag = `<script async src="${scriptUrl}" data-tracking-id="${website.trackingId}" data-min-interval="30000" data-enable-spa="false"></script>`;
    return {
      scriptTag,
      trackingId: website.trackingId,
      scriptUrl
    };
  }
} 